package com.biwin.module.org.starter.service.impl;

import com.biwin.common.app.exception.BwNotFoundException;
import com.biwin.core.main.property.BiWinLoginProperties;
import com.biwin.module.org.api.dto.SystemUserDto;
import com.biwin.module.org.api.enums.BwSystemUserExceptionEnum;
import com.biwin.module.org.api.service.ISystemUserService;
import com.biwin.module.org.api.vo.SystemUserVo;
import com.biwin.module.org.domain.entity.SystemUser;
import com.biwin.module.org.domain.mapper.SystemUserMapper;
import com.biwin.module.org.starter.repository.ISystemUserRepository;
import com.biwin.module.orm.starter.service.AbstractCurdService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Date;

/**
 * System User Service Implementation
 *
 * @author biwin
 * @since 0.0.1
 */
@Service
public class SystemUserServiceImpl extends AbstractCurdService<SystemUser, SystemUserVo, Long> implements ISystemUserService<SystemUser, SystemUserVo, Long> {

    private final ISystemUserRepository systemUserRepository;

    private final SystemUserMapper systemUserMapper;

    private final BiWinLoginProperties loginProperties;

    public SystemUserServiceImpl(ISystemUserRepository systemUserRepository, SystemUserMapper systemUserMapper,
                                 BiWinLoginProperties loginProperties) {
        super(systemUserRepository);
        this.systemUserRepository = systemUserRepository;
        this.systemUserMapper = systemUserMapper;
        this.loginProperties = loginProperties;
    }

    @Override
    //    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public SystemUserVo findByAccount(String account) {
        Assert.notNull(account, "account must be not null");
        SystemUser systemUser =
                systemUserRepository.findByAccount(account).orElseThrow(
                        () -> new BwNotFoundException(BwSystemUserExceptionEnum.USER_NOT_EXIST));
        return toVo(systemUser);
    }


    @Override
    public boolean checkUserExist(String username) {
        return systemUserRepository.countByAccount(username) > 0L;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePassword(Long userId, String newPassword) {
        SystemUser systemUser = super.findByIdE(userId);
        systemUser.setPassword(newPassword);
        systemUser.setPasswordLastModifyDate(new Date());
        systemUserRepository.save(systemUser);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePasswordFaultNum(Long userId, Integer faultNum) {
        SystemUser systemUser = super.findByIdE(userId);
        systemUser.setPasswordFaultNum(0);
        systemUserRepository.save(systemUser);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateLoginDate(Long userId) {
        SystemUser systemUser = super.findByIdE(userId);
        systemUser.setLastLoginDate(new Date());
        systemUserRepository.save(systemUser);
        return true;
    }

    /**
     * 底层的操作用户是否锁定的方法
     *
     * @param userId 指定用户id
     * @param locked true:锁定 or false:解锁
     * @return
     */
    private boolean lockUser(Long userId, boolean locked) {
        SystemUser systemUser = super.findByIdE(userId);
        systemUser.setLocked(locked);
        systemUserRepository.save(systemUser);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean lock(Long userId) {
        return lockUser(userId, true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unlock(Long userId) {
        return lockUser(userId, false);
    }

    /**
     * 禁用用户
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean disable(Long userId) {
        return enableUser(userId, false);
    }

    /**
     * 底层的操作用户是否有效的方法
     *
     * @param userId  指定用户id
     * @param enabled true:启用 or false:禁用
     * @return
     */
    private boolean enableUser(Long userId, boolean enabled) {
        SystemUser systemUser = super.findByIdE(userId);
        systemUser.setEffective(enabled);
        systemUserRepository.save(systemUser);
        return true;
    }

    /**
     * 启用用户
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean enable(Long userId) {
        return enableUser(userId, true);
    }

    /**
     * 添加 SystemUser 用户
     *
     * @param systemUserDto
     * @return
     */
    @Override
    public SystemUserVo add(SystemUserDto systemUserDto) {
        SystemUser systemUser = systemUserMapper.toEntity(systemUserDto);
        systemUserRepository.save(systemUser);
        return toVo(systemUser);
    }

    /**
     * 修改 SystemUser 用户
     *
     * @param systemUserDto
     * @return
     */
    @Override
    public SystemUserVo update(SystemUserDto systemUserDto) {
        SystemUser systemUser = systemUserMapper.mergeEntity(systemUserDto, findByIdE(systemUserDto.getId()));
        systemUserRepository.save(systemUser);
        return toVo(systemUser);
    }

    @Override
    protected SystemUserVo toVo(SystemUser entity) {
        return systemUserMapper.toVo(entity);
    }
}
